﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Common;
using AutoFacUtils;
using CashFlow.Db.DAL;
using CashFlow.Db.Entity;
using SysAdmin._00_Def;
using SysAdmin._01_Config;

namespace SysAdmin._03_Service._00_Db
{
    public class UserService
    {
        public static UserInfoAndReferenceUserInfo QueryByUserId(int userId)
        {
            using (var db = SqlSugarHelper.GetDb())
            {
                return db.Queryable<UserInfoEntity>()
                    .LeftJoin<UserInfoEntity>((u1, u2) => u1.ReferenceInvitationCode == u2.InvitationCode)
                    .Where((u1, u2) => u1.Id == userId)
                    .Select((u1, u2) => new UserInfoAndReferenceUserInfo
                    {
                        UserInfo = u1,
                        ReferenceUserInfo = u2
                    })
                    .First();
            }
        }

        public static UserInfoEntity QueryByInvitationCode(string invitationCode)
        {
            using (var db = SqlSugarHelper.GetDb())
            {
                var item = db.Queryable<UserInfoEntity>().Where(x => x.InvitationCode == invitationCode).First();
                return item;
            }
        }

        public static bool ResetPwd(UserInfoEntity userInfo)
        {
            using (var db = SqlSugarHelper.GetDb())
            {
                int n = db.Updateable(userInfo).ExecuteCommand();
                return n > 0;
            }
        }

        public static bool UpdateUser(UserInfoEntity userInfo)
        {
            using (var db = SqlSugarHelper.GetDb())
            {
                int n2 = db.Queryable<UserInfoEntity>()
                    .Where(x => x.Id != userInfo.Id && x.Phone == userInfo.Phone)
                    .Count();
                if (n2 == 0)
                {
                    int n = db.Updateable(userInfo).ExecuteCommand();
                    return n > 0;
                }
                else
                {
                    return false;
                }
            }
        }

        public static bool UpdateUser2(UserInfoEntity userInfo)
        {
            using (var db = SqlSugarHelper.GetDb())
            {
                int phone = db.Queryable<UserInfoEntity>()
                    .Where(x => x.Id != userInfo.Id && x.Phone == userInfo.Phone).Count();
                if (phone == 0)
                {
                    int n = db.Updateable(userInfo).ExecuteCommand();
                    return n > 0;
                }
                else
                {
                    throw new MyException("手机号码已存在！");
                }
            }
        }

        public static bool Delete(int userId)
        {
            using (var db = SqlSugarHelper.GetDb())
            {
                int n = db.Deleteable<ShopInfoEntity>(userId).ExecuteCommand();
                return n > 0;
            }
        }

        public static IList<UserInfoEntity> QueryAllChildUsersByUserId(int userId)
        {
            IList<UserInfoEntity> ls = new List<UserInfoEntity>();

            var users = new List<UserInfoEntity>();
            using (var db = SqlSugarHelper.GetDb())
            {
                users = db.Queryable<UserInfoEntity>().ToList();
            }

            var self = users.Where(x => x.Id == userId).FirstOrDefault();
            if (self != null)
            {
                Queue<string> queue = new Queue<string>();
                queue.Enqueue(self.InvitationCode);
                ls.Add(self);
                while (queue.Count > 0)
                {
                    var item = queue.Dequeue();
                    var ls2 = users.Where(x => x.ReferenceInvitationCode == item).ToList();
                    foreach (var item2 in ls2)
                    {
                        queue.Enqueue(item2.InvitationCode);
                        ls.Add(item2);
                    }
                }
            }

            return ls;
        }

        public static IList<UserInfoAndReferenceUserInfo> QueryAllUsersWithSameShopByUserId(int userId)
        {
            IList<UserInfoAndReferenceUserInfo> ls = new List<UserInfoAndReferenceUserInfo>();

            var shopInfo = ShopService.QueryShopInfoByUserId(userId);
            using (var db = SqlSugarHelper.GetDb())
            {
                var entity = db.Queryable<UserInfoEntity>()
                    .LeftJoin<UserInfoEntity>((u, ru) => u.ReferenceInvitationCode == ru.InvitationCode)
                    .Where((u, ru) => u.Id == userId)
                    .Select((u, ru) => new UserInfoAndReferenceUserInfo
                    {
                        UserInfo = u,
                        ReferenceUserInfo = ru
                    })
                    .First();
                if (entity != null)
                {
                    ls.Add(entity);

                    Queue<string> queue = new Queue<string>();
                    string referenceInvitationCode = entity.UserInfo.InvitationCode;

                    var ls2 = db.Queryable<UserInfoEntity>()
                        .InnerJoin<ShopUserEntity>((u, s) => u.Id == s.UserId && s.ShopManagerUserId == shopInfo.ShopManagerUserId)
                        .LeftJoin<UserInfoEntity>((u, s, ru) => u.ReferenceInvitationCode == ru.InvitationCode)
                        .Where((u, s, ru) => u.ReferenceInvitationCode == referenceInvitationCode)
                        .Select((u, s, ru) => new UserInfoAndReferenceUserInfo
                        {
                            UserInfo = u,
                            ReferenceUserInfo = ru
                        })
                        .ToList();
                    foreach (var item in ls2)
                    {
                        ls.Add(item);
                        queue.Enqueue(item.UserInfo.InvitationCode);
                    }

                    while (queue.Count > 0)
                    {
                        string referenceInvitationCode2 = queue.Dequeue();
                        var ls3 = db.Queryable<UserInfoEntity>()
                            .InnerJoin<ShopUserEntity>((u, s) => u.Id == s.UserId && s.ShopManagerUserId == shopInfo.ShopManagerUserId)
                            .LeftJoin<UserInfoEntity>((u, s, ru) => u.ReferenceInvitationCode == ru.InvitationCode)
                            .Where((u, s, ru) => u.ReferenceInvitationCode == referenceInvitationCode2)
                            .Select((u, s, ru) => new UserInfoAndReferenceUserInfo
                            {
                                UserInfo = u,
                                ReferenceUserInfo = ru
                            })
                            .ToList();
                        foreach (var item in ls3)
                        {
                            ls.Add(item);
                            queue.Enqueue(item.UserInfo.InvitationCode);
                        }
                    }
                }
            }

            return ls;
        }

        public static IList<UserInfoAndReferenceUserInfo> QueryByWhere2(string phone
            , string name)
        {
            using (var db = SqlSugarHelper.GetDb())
            {
                var ls = db.Queryable<UserInfoEntity>()
                    .LeftJoin<UserInfoEntity>((u1, u2) => u1.ReferenceInvitationCode == u2.InvitationCode)
                    .Where((u1, u2) => u1.Name.Contains(name)
                        && u1.Phone.Contains(phone)
                        && u1.Id != MyConfig.MTCPUserId)
                    .Select((u1, u2) => new UserInfoAndReferenceUserInfo
                    {
                        UserInfo = u1,
                        ReferenceUserInfo = u2
                    })
                    .ToList();
                return ls;
            }
        }

        public static IList<UserInfoAndReferenceUserInfo> QueryAllUsers()
        {
            using (var db = SqlSugarHelper.GetDb())
            {
                var ls = db.Queryable<UserInfoEntity>()
                        .InnerJoin<UserInfoEntity>((u1, u2) => u1.ReferenceInvitationCode == u2.InvitationCode)
                        .Where((u1, u2) => u1.Id != MyConfig.MTCPUserId)
                        .Select((u1, u2) => new UserInfoAndReferenceUserInfo
                        {
                            UserInfo = u1,
                            ReferenceUserInfo = u2
                        })
                        .ToList();
                return ls;
            }
        }

        public static IList<UserInfoEntity> QueryAllUsers2()
        {
            using (var db = SqlSugarHelper.GetDb())
            {
                var ls = db.Queryable<UserInfoEntity>()
                        .Where(x => x.Id != MyConfig.MTCPUserId)
                        .ToList();
                return ls;
            }
        }

        public static IList<UserInfoAndReferenceUserInfo> QueryAllByWhere(string name
            , string invitationCode
            , string reference
            , string referenceInvitationCode
            , string phone
            , string date)
        {
            using (var db = SqlSugarHelper.GetDb())
            {
                var query = db.Queryable<UserInfoEntity>()
                    .InnerJoin<UserInfoEntity>((u1, u2) => u1.ReferenceInvitationCode == u2.InvitationCode);
                if (!string.IsNullOrEmpty(name))
                {
                    query = query.Where((u1, u2) => u1.Name.Contains(name));
                }
                if (!string.IsNullOrEmpty(invitationCode))
                {
                    query = query.Where((u1, u2) => u1.InvitationCode.Contains(invitationCode));
                }
                if (!string.IsNullOrEmpty(reference))
                {
                    query = query.Where((u1, u2) => u2.Name.Contains(reference));
                }
                if (!string.IsNullOrEmpty(referenceInvitationCode))
                {
                    query = query.Where((u1, u2) => u1.ReferenceInvitationCode.Contains(referenceInvitationCode));
                }
                if (!string.IsNullOrEmpty(phone))
                {
                    query = query.Where((u1, u2) => u1.Phone.Contains(phone));
                }
                if (!string.IsNullOrEmpty(date))
                {
                    query = query.Where((u1, u2) => u1.CreateTime.ToString().Substring(0, 10) == date);
                }

                var ls = query.Select((u1, u2) => new UserInfoAndReferenceUserInfo
                {
                    UserInfo = u1,
                    ReferenceUserInfo = u2
                }).ToList();
                return ls;
            }
        }
    }
}
